<?php
/**
 * CDbCommand 扩展类，
 * 重写 getConnection 方法，用以配置主从库选择，减少主数据库连接次数
 * 缓存 show 语句，减少数据库查询次数
 */
 
class CDbCommandExt extends CDbCommand {
	
	/**
	 * 是否为 分库分表模式, 缓存SQL时 根据该值判断，并作相应处理
	 * @var Boolean
	 */
	public static $isShareded = true;
	
	public function getConnection() {
		$conn = parent::getConnection();
		
		if(
			!CDbManager::isMaster() && 
			self::isReadOperation($this->getText()) &&
			$conn->enableSlave &&
			!$conn->getCurrentTransaction()
		) {
			return $conn->slave;
		}
		
		$conn->active = true;
		return $conn;
	}
	
	/**
	 * 缓存部分查询
	 * @see parent::queryRow
	 */
	public function queryRow($fetchAssociative = true, $params = array()) {
		$data = $this->sqlCache();
		if(empty($data)) {
			$data = parent::queryRow($fetchAssociative, $params);
			$this->sqlCache($data);
		}
		
		return $data;
	}
	
	/**
	 * 缓存部分查询
	 * @see parent::queryAll
	 */
	public function queryAll($fetchAssociative = true, $params = array()) {
		$data = $this->sqlCache();
		if(empty($data)) {
			$data = parent::queryAll($fetchAssociative, $params);
			$this->sqlCache($data);
		}
		
		return $data;
	}
	
	/**
	 * 缓存SQL语句
	 */
	public function sqlCache($data = null) {
		$sql = $this->getText();
		
		if(is_string($sql) && preg_match("#^SHOW#", trim($sql))) {
			self::$isShareded && $sql = preg_replace("#_[\da-zA-Z]+`$#", '`', $sql);
			$hash = substr(md5($sql), 0, 16);
			
			$cache = Yii::app()->cache;
			$key = 'sql_'.$hash;
			
			if(empty($data)) return $cache->get($key);
			else $cache->set($key, $data, 86400);
		}
	}
	
	/**
	 * 从sql语句判断是否为读取操作
	 * @return Boolean
	 */
	public static function isReadOperation($sql) {
		return preg_match("#^(SELECT|SHOW|DESCRIBE|PRAGMA)#i", ltrim($sql));
	}
}